/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 UJF.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.tools;

import static java.net.HttpURLConnection.HTTP_ACCEPTED;
import static java.net.HttpURLConnection.HTTP_NO_CONTENT;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public final class JsonRestTools {

    private final static int BUFFER_SIZE = 0x10000;

    public static final String CONTENT_TYPE_JSON = "application/json";

    private static final String CHARSET_NAME = "UTF-8";

    public static final String doGet(final String gwurl) throws MalformedURLException, IOException {
        String result;
        // Send data
        URL url = new URL(gwurl);
        HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
        httpCon.setDoOutput(true);
        result = read(httpCon.getInputStream());
        httpCon.disconnect();
        // TODO Handle Exception
        return result;
    }

    public static final void doPut(final String gwurl, final String content) throws Exception {
        // Send data
        URL url = new URL(gwurl);
        HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
        httpCon.setDoOutput(true);
        httpCon.setRequestProperty("Content-Type", CONTENT_TYPE_JSON);
        httpCon.setRequestMethod("PUT");
        OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
        out.write(content);
        out.close();
        if (httpCon.getResponseCode() != HTTP_NO_CONTENT && httpCon.getResponseCode() != HTTP_ACCEPTED) {
            throw new Exception("Error Http Code: " + httpCon.getResponseCode());
        }
        httpCon.disconnect();
    }

    public static final void doDelete(final String gwurl) throws Exception {
        // Send data
        URL url = new URL(gwurl);
        HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
        httpCon.setDoOutput(false);
        httpCon.setRequestMethod("DELETE");
        httpCon.connect();
        if (httpCon.getResponseCode() != HTTP_NO_CONTENT) {
            throw new Exception("Error Http Code: " + httpCon.getResponseCode());
        }
        httpCon.disconnect();
    }

    /**
     * Read an InputStream and return the result as a String.
     * @param in
     * @return
     * @throws IOException
     */
    public static final String read(InputStream in) throws IOException {
        final char[] buffer = new char[BUFFER_SIZE];
        StringBuilder out = new StringBuilder();
        Reader reader = new InputStreamReader(in, CHARSET_NAME);
        int read;
        do {
            read = reader.read(buffer, 0, buffer.length);
            if (read > 0) {
                out.append(buffer, 0, read);
            }
        } while (read >= 0);

        return out.toString();
    }

    /**
     * @param json, A String representation of a JSONObject
     * @return A Collection of JSONObject
     * @throws IllegalArgumentException if the given String is not a valid
     *         JSONObject or JSONArray
     */
    public static final Collection<JSONObject> stringToJSONObjects(String json) throws IllegalArgumentException {
        Collection<JSONObject> datas = new ArrayList<JSONObject>();
        try {
            if (json.startsWith("[")) {
                JSONArray array = new JSONArray(json);
                for (int i = 0; i < array.length(); i++) {
                    datas.add(array.getJSONObject(i));
                }
            } else {
                datas.add(new JSONObject(json));
            }
        } catch (JSONException e) {
            throw new IllegalArgumentException("The given String must be a valid jsonobject or jsonarray", e);
        }
        return datas;
    }
}
